package netty.client;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import netty.protocol.Hello;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class ProtoClientHandler extends SimpleChannelInboundHandler<Object> {

    public ProtoClientHandler() {
        log.info(">>> init {}", this.toString());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws InterruptedException {
        AtomicInteger seq = new AtomicInteger();

        for (int i = 0; i < 10; i++) {
            ctx.channel().eventLoop().schedule(() -> {
                final Hello.Protocol.Builder builder;
                if (Math.random() > 0.5) {
                    builder = Hello.Protocol.newBuilder()
                            .setType(Hello.Protocol.DataType.Chat)
                            .setChat(Hello.ChatMessage.newBuilder().setUserId(seq.incrementAndGet()).setMsg("chat.message"))
                    ;
                } else {
                    builder = Hello.Protocol.newBuilder()
                            .setType(Hello.Protocol.DataType.Join)
                            .setJoin(Hello.JoinMessage.newBuilder().setName("join.name").setUserId(seq.incrementAndGet()))
                    ;
                }

                log.info(">>> send, {}", builder);
                ctx.channel().writeAndFlush(builder.build());


            }, i + 1, TimeUnit.SECONDS);
        }

        ctx.channel().eventLoop().schedule(() -> {
            Hello.Protocol.Builder builder = Hello.Protocol.newBuilder()
                    .setType(Hello.Protocol.DataType.Leave)
                    .setLeave(Hello.LeaveMessage.newBuilder().setUserId(seq.incrementAndGet()).setName("leave.name"));

            ctx.channel().writeAndFlush(builder.build()).addListener(ChannelFutureListener.CLOSE);
        }, 10, TimeUnit.SECONDS);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        // Server is supposed to send nothing, but if it sends something, discard it.
        log.info("receive data: {}, {}", msg, ctx.channel().remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}
